package com.cube.dp.cor.filter;

import com.cube.dp.cor.context.TransformContext;
import com.cube.dp.cor.wrapper.NamingTransformFilterWrapper;
import com.cube.dp.cor.wrapper.TimeConsumingTransformFilterWrapper;
import com.cube.dp.cor.wrapper.WrappedTransformFilterChain;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author cube.li
 * @date 2021/12/13 21:53
 * <p>
 * 短链转换过滤器链工厂
 */
@Component
public class TransformFilterChainFactory implements BeanFactoryAware {

    private ListableBeanFactory beanFactory;

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = (ListableBeanFactory) beanFactory;
    }

    /**
     * 根据短链转换上下文创建默认的短链转换过滤器链
     *
     * @param context 上下文
     * @return 过滤器链
     */
    public TransformFilterChain defaultFilterChain(TransformContext context) {
        //从容器中获取所有的短链转换过滤器
        Map<String, TransformFilter> filterMap = beanFactory.getBeansOfType(TransformFilter.class);

        DefaultTransformFilterChain chain = new DefaultTransformFilterChain(context);

        chain.addTransformFilters(new ArrayList<>(filterMap.values()));
        return chain;
    }

    /**
     * 根据短链转换上下文创建包装后的短链转换过滤器链
     *
     * @param context 上下文
     * @return 包装后的过滤器链
     */
    public WrappedTransformFilterChain wrappedFilterChain(TransformContext context) {
        //从容器中获取所有的短链转换过滤器
        Map<String, TransformFilter> filterMap = beanFactory.getBeansOfType(TransformFilter.class);

        Set<Map.Entry<String, TransformFilter>> filterSet = filterMap.entrySet();

        WrappedTransformFilterChain chain = new WrappedTransformFilterChain(context);
        chain.addTransformFilterWrappers(filterSet.stream()
                .map(entry -> new NamingTransformFilterWrapper(new TimeConsumingTransformFilterWrapper(entry.getValue()), entry.getKey()))
                .collect(Collectors.toList()));
        return chain;
    }
}
